﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twodi.Implemented;
using Twodi.Aspect.Interfaces;
using Microsoft.Xna.Framework;

namespace Twodi.Behavior.Implemented
{
    /// <summary>
    /// Comportamento de Animação.
    /// </summary>
    public class AnimationBehavior : AbstractBehavior<ITextureAspect>
    {
        /// <summary>
        /// Construtor do comportamento.
        /// </summary>
        /// <param name="component">Componente a ser animado.</param>
        public AnimationBehavior(ITextureAspect component)
            : base(component)
        {
            Animations = new Dictionary<string, Animation>();
            Animation = "";
        }

        /// <summary>
        /// Lógica do comportamento de animação.
        /// </summary>
        /// <param name="gameTime">Tempo do jogo.</param>
        public override void Update(GameTime gameTime)
        {
            if (Animation != null && Animation != string.Empty)
            {
                Animations[Animation].Update(gameTime);
            }
        }

        /// <summary>
        /// Adicionar animações ao comportamento.
        /// </summary>
        /// <param name="frames">Animações a ser adicionados.</param>
        public void Add(params Animation[] animations)
        {
            for (int i = 0; i < animations.Length; i++)
            {
                this.Animations.Add(animations[i].Name, animations[i]);
            }
        }

        /// <summary>
        /// Criar nova animação.
        /// </summary>
        /// <param name="name">Nome da animação.</param>
        /// <param name="type">Tipo de animação.</param>
        /// <param name="frames">Lista de Frames da animação.</param>
        public void Create(String name, AnimationType type, params AnimationFrame[] frames)
        {
            this.Animations.Add(name, new Animation(name, this.Component)
            {
                Type = type,
                Frames = new List<AnimationFrame>(frames)
            });
        }

        /// <summary>
        /// Animação atual do componente.
        /// </summary>
        #region Attribute Animation

        /// <summary>
        /// Animação atual do componente.
        /// </summary>
        private String animation;

        /// <summary>
        /// Property: Animação atual do componente.
        /// </summary>
        public String Animation
        {
            get { return this.animation; }
            set
            {
                if (!animations.Keys.Contains(value))
                {
                    return;
                }
                this.animation = value;
                onAnimationChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Evento invocado quando valor de "Animation" é alterado(a).
        /// </summary>
        public event EventHandler<EventArgs> AnimationChanged;

        /// <summary>
        /// Método responsavel por invocar o evento AnimationChanged;
        /// </summary>
        protected virtual void onAnimationChanged(EventArgs e)
        {
            if (AnimationChanged != null)
            {
                AnimationChanged(this, e);
            }
        }

        #endregion Attribute Animation

        /// <summary>
        /// Dicionario de Animações do componente.
        /// </summary>
        #region Attribute Animations

        /// <summary>
        /// Dicionario de Animações do componente.
        /// </summary>
        private Dictionary<String, Animation> animations;

        /// <summary>
        /// Property: Dicionario de Animações do componente.
        /// </summary>
        public Dictionary<String, Animation> Animations
        {
            get { return this.animations; }
            set
            {
                this.animations = value;
                onAnimationsChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Evento invocado quando valor de "Animations" é alterado(a).
        /// </summary>
        public event EventHandler<EventArgs> AnimationsChanged;

        /// <summary>
        /// Método responsavel por invocar o evento AnimationsChanged;
        /// </summary>
        protected virtual void onAnimationsChanged(EventArgs e)
        {
            if (AnimationsChanged != null)
            {
                AnimationsChanged(this, e);
            }
        }

        #endregion Attribute Animations
    }
}
